home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / formats / iff / newiff.lzh / NewIFF / NewIFF.lzh / newiff / modules / ilbmr.c < prev    next >
C/C++ Source or Header  |  1992-05-18  |  10KB  |  366 lines

  1. /* ilbmr.c --- ILBM loading routines for use with iffparse */
  2.  
  3. /*----------------------------------------------------------------------*
  4.  * ILBMR.C  Support routines for reading ILBM files.
  5.  * (IFF is Interchange Format File.)
  6.  *
  7.  * Based on code by Jerry Morrison and Steve Shaw, Electronic Arts.
  8.  * This software is in the public domain.
  9.  * Modified for iffparse.library 05/90
  10.  * This version for the Commodore-Amiga computer.
  11.  *
  12.  * 37.9 04/92
  13.  *----------------------------------------------------------------------*/
  14. #define INTUI_V36_NAMES_ONLY
  15.  
  16. #include "iffp/ilbm.h"
  17. #include "iffp/packer.h"
  18. #include "iffp/ilbmapp.h"
  19.  
  20. #define movmem CopyMem
  21.  
  22. #define MaxSrcPlanes (25)
  23.  
  24. extern struct Library *GfxBase;
  25.  
  26. /*---------- loadbody ---------------------------------------------------*/
  27.  
  28. LONG loadbody(iff, bitmap, bmhd)
  29. struct IFFHandle *iff;
  30. struct BitMap *bitmap;
  31. BitMapHeader *bmhd;
  32.     {
  33.     BYTE *buffer;
  34.     ULONG bufsize;
  35.     LONG error = 1;
  36.  
  37.     D(bug("In loadbody\n"));
  38.  
  39.     if(!(currentchunkis(iff,ID_ILBM,ID_BODY)))
  40.         {
  41.         message(SI(MSG_IFFP_NOBODY));    /* Maybe it's a palette */
  42.         return(IFF_OKAY);
  43.         }
  44.  
  45.     if((bitmap)&&(bmhd))
  46.         {
  47.         D(bug("Have bitmap and bmhd\n"));
  48.  
  49.         bufsize = MaxPackedSize(RowBytes(bmhd->w)) << 4;
  50.             if(!(buffer = AllocMem(bufsize,0L)))
  51.         {
  52.         D(bug("Buffer alloc of %ld failed\n",bufsize));
  53.         return(IFFERR_NOMEM);
  54.         }
  55.         error = loadbody2(iff, bitmap, NULL, bmhd, buffer, bufsize);
  56.         D(bug("Returned from getbody, error = %ld\n",error));
  57.         }
  58.     FreeMem(buffer,bufsize);
  59.     return(error);
  60.     }
  61.  
  62.  
  63. /* like the old GetBODY */
  64. LONG loadbody2(iff, bitmap, mask, bmhd, buffer, bufsize)
  65. struct IFFHandle *iff;
  66. struct BitMap *bitmap;
  67. BYTE *mask;
  68. BitMapHeader *bmhd;
  69. BYTE *buffer;
  70. ULONG bufsize;
  71.    {
  72.    UBYTE srcPlaneCnt = bmhd->nPlanes;   /* Haven't counted for mask plane yet*/
  73.    WORD srcRowBytes = RowBytes(bmhd->w);
  74.    WORD destRowBytes = bitmap->BytesPerRow;
  75.    LONG bufRowBytes = MaxPackedSize(srcRowBytes);
  76.    int nRows = bmhd->h;
  77.    WORD compression = bmhd->compression;
  78.    register int iPlane, iRow, nEmpty;
  79.    register WORD nFilled;
  80.    BYTE *buf, *nullDest, *nullBuf, **pDest;
  81.    BYTE *planes[MaxSrcPlanes]; /* array of ptrs to planes & mask */
  82.    struct ContextNode *cn;
  83.  
  84.    D(bug("srcRowBytes = %ld\n",srcRowBytes));
  85.  
  86.    cn = CurrentChunk(iff);
  87.  
  88.    if (compression > cmpByteRun1)
  89.       return(CLIENT_ERROR);
  90.  
  91.    D(bug("loadbody2: compression=%ld srcBytes=%ld bitmapBytes=%ld\n",
  92.         compression, srcRowBytes, bitmap->BytesPerRow));
  93.    D(bug("loadbody2: bufsize=%ld bufRowBytes=%ld, srcPlaneCnt=%ld\n",
  94.             bufsize, bufRowBytes, srcPlaneCnt));
  95.  
  96.    /* Complain if client asked for a conversion GetBODY doesn't handle.*/
  97.    if ( srcRowBytes  >  bitmap->BytesPerRow  ||
  98.          bufsize < bufRowBytes * 2  ||
  99.          srcPlaneCnt > MaxSrcPlanes )
  100.       return(CLIENT_ERROR);
  101.  
  102.    D(bug("loadbody2: past conversion checks\n"));
  103.  
  104.    if (nRows > bitmap->Rows)   nRows = bitmap->Rows;
  105.  
  106.    D(bug("loadbody2: srcRowBytes=%ld, srcRows=%ld, srcDepth=%ld, destDepth=%ld\n",
  107.         srcRowBytes, nRows, bmhd->nPlanes, bitmap->Depth));
  108.    
  109.    /* Initialize array "planes" with bitmap ptrs; NULL in empty slots.*/
  110.    for (iPlane = 0; iPlane < bitmap->Depth; iPlane++)
  111.       planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
  112.    for ( ;  iPlane < MaxSrcPlanes;  iPlane++)
  113.       planes[iPlane] = NULL;
  114.  
  115.    /* Copy any mask plane ptr into corresponding "planes" slot.*/
  116.    if (bmhd->masking == mskHasMask)
  117.     {
  118.           if (mask != NULL)
  119.              planes[srcPlaneCnt] = mask;  /* If there are more srcPlanes than
  120.                * dstPlanes, there will be NULL plane-pointers before this.*/
  121.           else
  122.              planes[srcPlaneCnt] = NULL;  /* In case more dstPlanes than src.*/
  123.           srcPlaneCnt += 1;  /* Include mask plane in count.*/
  124.           }
  125.  
  126.    /* Setup a sink for dummy destination of rows from unwanted planes.*/
  127.    nullDest = buffer;
  128.    buffer  += srcRowBytes;
  129.    bufsize -= srcRowBytes;
  130.  
  131.    /* Read the BODY contents into client's bitmap.
  132.     * De-interleave planes and decompress rows.
  133.     * MODIFIES: Last iteration modifies bufsize.*/
  134.  
  135.    buf = buffer + bufsize;  /* Buffer is currently empty.*/
  136.    for (iRow = nRows; iRow > 0; iRow--)
  137.     {
  138.           for (iPlane = 0; iPlane < srcPlaneCnt; iPlane++)
  139.         {
  140.          pDest = &planes[iPlane];
  141.  
  142.             /* Establish a sink for any unwanted plane.*/
  143.             if (*pDest == NULL)
  144.         {
  145.             nullBuf = nullDest;
  146.                 pDest   = &nullBuf;
  147.                 }
  148.  
  149.             /* Read in at least enough bytes to uncompress next row.*/
  150.             nEmpty  = buf - buffer;      /* size of empty part of buffer.*/
  151.             nFilled = bufsize - nEmpty;      /* this part has data.*/
  152.         if (nFilled < bufRowBytes)
  153.         {
  154.             /* Need to read more.*/
  155.  
  156.             /* Move the existing data to the front of the buffer.*/
  157.             /* Now covers range buffer[0]..buffer[nFilled-1].*/
  158.                 movmem(buf, buffer, nFilled);  /* Could be moving 0 bytes.*/
  159.  
  160.                 if(nEmpty > ChunkMoreBytes(cn))
  161.             {
  162.                        /* There aren't enough bytes left to fill the buffer.*/
  163.                        nEmpty = ChunkMoreBytes(cn);
  164.                        bufsize = nFilled + nEmpty;  /* heh-heh */
  165.                        }
  166.  
  167.             /* Append new data to the existing data.*/
  168.                 if(ReadChunkBytes(iff, &buffer[nFilled], nEmpty) < nEmpty)
  169.             return(CLIENT_ERROR);
  170.  
  171.                 buf     = buffer;
  172.             nFilled = bufsize;
  173.             nEmpty  = 0;
  174.             }
  175.  
  176.          /* Copy uncompressed row to destination plane.*/
  177.             if(compression == cmpNone)
  178.         {
  179.                 if(nFilled < srcRowBytes)  return(IFFERR_MANGLED);
  180.             movmem(buf, *pDest, srcRowBytes);
  181.             buf    += srcRowBytes;
  182.                 *pDest += destRowBytes;
  183.                 }
  184.         else
  185.         {
  186.              /* Decompress row to destination plane.*/
  187.                 if ( unpackrow(&buf, pDest, nFilled,  srcRowBytes) )
  188.                     /*  pSource, pDest, srcBytes, dstBytes  */
  189.                        return(IFFERR_MANGLED);
  190.             else *pDest += (destRowBytes - srcRowBytes);
  191.         }
  192.         }
  193.     }
  194.    return(IFF_OKAY);
  195.    }
  196.  
  197.  
  198. /* ----------- getcolors ------------- */
  199.  
  200. /* getcolors - allocates a ilbm->colortable for at least 32 registers
  201.  *      and loads CMAP colors into it, setting ilbm->ncolors to number
  202.  *      of colors actually loaded.
  203.  */ 
  204. LONG getcolors(struct ILBMInfo *ilbm)
  205.     {
  206.     struct IFFHandle    *iff;
  207.     int error = 1;
  208.  
  209.     if(!(iff=ilbm->ParseInfo.iff))    return(CLIENT_ERROR);
  210.  
  211.     if(!(error = alloccolortable(ilbm)))
  212.        error = loadcmap(iff, ilbm->colortable, &ilbm->ncolors);
  213.     if(error) freecolors(ilbm);
  214.     D(bug("getcolors: error = %ld\n",error));
  215.     return(error);
  216.     }
  217.  
  218.  
  219. /* alloccolortable - allocates ilbm->colortable and sets ilbm->ncolors
  220.  *    to the number of colors we have room for in the table.
  221.  */ 
  222.  
  223. LONG alloccolortable(struct ILBMInfo *ilbm)
  224.     {
  225.     struct IFFHandle    *iff;
  226.     struct    StoredProperty    *sp;
  227.  
  228.     LONG    error = CLIENT_ERROR;
  229.     ULONG    ctabsize;
  230.     USHORT    ncolors;
  231.  
  232.     if(!(iff=ilbm->ParseInfo.iff))    return(CLIENT_ERROR);
  233.  
  234.     if(sp = FindProp (iff, ID_ILBM, ID_CMAP))
  235.         {
  236.         /*
  237.          * Compute the size table we need
  238.          */
  239.         ncolors = sp->sp_Size / 3;        /* how many in CMAP */
  240.         ncolors = MAX(ncolors, 32);
  241.  
  242.         ctabsize = ncolors * sizeof(Color4);
  243.         if(ilbm->colortable = 
  244.            (Color4 *)AllocMem(ctabsize,MEMF_CLEAR|MEMF_PUBLIC))
  245.             {
  246.             ilbm->ncolors = ncolors;
  247.             ilbm->ctabsize = ctabsize;
  248.             error = 0L;
  249.             }
  250.         else error = IFFERR_NOMEM;
  251.         }
  252.     D(bug("alloccolortable for %ld colors: error = %ld\n",ncolors,error));
  253.     return(error);
  254.     }
  255.  
  256.  
  257. void freecolors(struct ILBMInfo *ilbm)
  258.     {
  259.     if(ilbm->colortable)
  260.         {
  261.         FreeMem(ilbm->colortable, ilbm->ctabsize);
  262.         }
  263.     ilbm->colortable = NULL;
  264.     ilbm->ctabsize = 0;
  265.     }
  266.  
  267.  
  268.  
  269. /* Passed IFFHandle, pointer to colortable array, and pointer to
  270.  * a USHORT containing number of colors caller has space to hold,
  271.  * loads the colors and sets pNcolors to the number actually read.
  272.  *
  273.  * NOTE !!! - Old GetCMAP passed a pointer to a UBYTE for pNcolors
  274.  *            This one is passed a pointer to a USHORT
  275.  */
  276. LONG loadcmap(struct IFFHandle *iff, WORD *colortable,USHORT *pNcolors)
  277.     {
  278.     register struct StoredProperty    *sp;
  279.     register LONG            idx;
  280.     register ULONG            ncolors;
  281.     register UBYTE            *rgb;
  282.     LONG                r, g, b;
  283.  
  284.     if(!(colortable))
  285.         {
  286.         message(SI(MSG_IFFP_NOCOLORS));
  287.         return(1);
  288.         }
  289.  
  290.     if(!(sp = FindProp (iff, ID_ILBM, ID_CMAP)))    return(1);
  291.  
  292.     rgb = sp->sp_Data;
  293.     ncolors = sp->sp_Size / sizeofColorRegister;
  294.     if(*pNcolors < ncolors)    ncolors = *pNcolors;
  295.     *pNcolors = ncolors;
  296.  
  297.     idx = 0;
  298.         while (ncolors--) 
  299.                 {
  300.                 r = (*rgb++ & 0xF0) << 4;
  301.                 g = *rgb++ & 0xF0;
  302.                 b = *rgb++ >> 4;
  303.                 colortable[idx] = r | g | b;
  304.                 idx++;
  305.                 }
  306.         return(0);
  307.         }
  308.  
  309. /*
  310.  * Returns CAMG or computed mode for storage in ilbm->camg
  311.  *
  312.  * ilbm->Bmhd structure must be initialized prior to this call.
  313.  */
  314. ULONG getcamg(struct ILBMInfo *ilbm)
  315.     {
  316.     struct IFFHandle *iff;
  317.     struct StoredProperty *sp;
  318.     UWORD  wide,high,deep;
  319.     ULONG modeid = 0L;
  320.  
  321.         if(!(iff=ilbm->ParseInfo.iff))    return(0L);
  322.  
  323.     wide = ilbm->Bmhd.pageWidth;
  324.     high = ilbm->Bmhd.pageHeight;
  325.     deep = ilbm->Bmhd.nPlanes;
  326.  
  327.     D(bug("Getting CAMG for w=%ld h=%ld d=%ld ILBM\n",wide,high,deep));
  328.  
  329.         /*
  330.          * Grab CAMG's idea of the viewmodes.
  331.          */
  332.         if (sp = FindProp (iff, ID_ILBM, ID_CAMG))
  333.                 {
  334.                 modeid = (* (ULONG *) sp->sp_Data);
  335.  
  336.                 /* knock bad bits out of old-style 16-bit viewmode CAMGs
  337.                  */
  338.                 if((!(modeid & MONITOR_ID_MASK))||
  339.           ((modeid & EXTENDED_MODE)&&(!(modeid & 0xFFFF0000))))
  340.                    modeid &= 
  341.             (~(EXTENDED_MODE|SPRITES|GENLOCK_AUDIO|GENLOCK_VIDEO|VP_HIDE));
  342.  
  343.                 /* check for bogus CAMG like DPaintII brushes
  344.                  * with junk in upper word and extended bit
  345.                  * not set in lower word.
  346.                  */
  347.                 if((modeid & 0xFFFF0000)&&(!(modeid & 0x00001000))) sp=NULL;
  348.                 }
  349.  
  350.         if(!sp) {
  351.                 /*
  352.                  * No CAMG (or bad CAMG) present; use computed modes.
  353.                  */
  354.                 if (wide >= 640)        modeid = HIRES;
  355.                 if (high >= 400)        modeid |= LACE;
  356.                 if (deep == 6)
  357.                         {
  358.                         modeid |= ilbm->EHB ? EXTRA_HALFBRITE : HAM;
  359.                         }
  360.         D(bug("No CAMG found - using mode $%08lx\n",modeid));
  361.                 }
  362.  
  363.     D(bug("getcamg: modeid = $%08lx\n",modeid));
  364.     return(modeid);
  365.     }
  366.